//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef enum {
    false,
    true
} bool;
int cc = 0; // 标识当前字符的下标
// -------------------相关函数-------------------
//函数声明
int judge(char a[], char b[]);
// 1、当前字符读到ch中
void getch(char* ch, char code[])
{
    *ch = code[cc];
    cc++; // 跳到下一个字符
}
// 2、过滤空格符，读取非空格符存入ch中
void getnbc(char* ch, char code[])
{
    getch(ch, code);
    if ((*ch) == ' ') {
        cc++;
        getch(ch, code);
    }
}
// 3、将字符ch接到arr后面
void concat(char arr[], int* strlen, char ch)
{
    arr[*strlen] = ch;
    (*strlen)++;
}

// 5、判断ch是否为字母
bool letter(char ch)
{
    return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ? true : false;
}
// 6、判断是否为数字
bool digit(char ch)
{
    return ch >= '0' && ch <= '9' ? true : false;
}

// 7、识别标识符(含关键字)
int IdentifyMark(char code[], char sym[], int* len, char* ch)
{
    char mark[20];
    mark[0] = *ch;
    concat(sym, len, *ch); //  将ch接到sym中
    getch(ch, code); //取下一个字符
    int* key[7] = { "void", "main", "int", "if", "else", "return", "float" };
    int k = 1, t;
    while (letter(*ch) == true || digit(*ch) == true) {
        mark[k] = *ch;
        concat(sym, len, *ch);
        getch(ch, code);
        k++;
    }
    mark[k] = 0;
    int result = -1;
    for (t = 0; t < 7; t++) {
        result = judge(mark, key[t]);
        if (result == 1) {
            return 1; // 关键字
        }
    }
    return 0; //标识符
}

// 8、识别常数
void IdentifyConst(char code[], char sym[], int* len, char* ch)
{
    concat(sym, len, *ch); //  将ch接到sym中
    getch(ch, code); //取下一个字符

    while (*ch == '.' || digit(*ch) == true) {
        concat(sym, len, *ch);
        getch(ch, code);
    }
}
// 9、判断两个字符串是否相同，相同返回1，不同返回0
int judge(char a[], char b[])
{
    int i = 0;
    while (a[i] != 0) {
        if (a[i] != b[i])
            return 0;
        i++;
    }
    if (b[i] != 0)
        return 0;
    return 1;
}
// 展示token
void showToken(int token[100][2], char sym[], int count)
{
    int i, j;
    for (i = 0; i < count; i++) {
        char mark[20];
        int k = 0, t;
        for (j = token[i][1]; j < token[i + 1][1]; j++) {
            mark[k] = sym[j];
            k++;
        }
        mark[k] = 0; // 字符串结尾标志
        if (token[i][0] == 0) {
            printf("{标识符，%s", mark);
        } else if (token[i][0] == 1) {
            printf("{关键字,%s}", mark);
        } else {
            printf("{常量，%s", mark);
        }
        printf("}\t");
    }
}

// 计算思维，用工作单元来解决问题
int main()
{
    char code[500];
    FILE* fp = NULL;
    fp = fopen("./pratice1.txt", "r");
    if (fp == NULL) {
        printf("文件打开失败！");
        exit(0);
    }

    fgets(code, 500, fp);

    printf("str:%s", code);
    while (code[0] != '$') {

        char ch = code[0];
        char sym[100]; // 标识符名表
        int symlen = 0; // 标识符名表的长度
        int token[100][2];
        int i = 0;

        int intConst[100]; // 常量表
        int j = 0; //记录常量
        cc = 0;
        while (ch != '#') { // 当当前字符为'#'时结束
            int type; //分辨标识符和关键字
            getch(&ch, code);
            // 如果当前字符为字母
            if (letter(ch)) {
                token[i][1] = symlen;
                type = IdentifyMark(code, sym, &symlen, &ch);
                token[i][0] = type; // 0表示为标识符，1表示为关键字
                i++;
            }
            // 如果当前字符为数字
            else if (digit(ch)) {
                token[i][0] = 2; // 2表示为常量
                token[i][1] = symlen;
                IdentifyConst(code, sym, &symlen, &ch);
                i++;
            }
            // 否则应为界限符或运算符
            else {
            }
        }
        token[i][1] = symlen; //记录最后一个元素的结尾下标
        showToken(token, sym, i);
        fgets(code, 500, fp);
    }
    system("pause");
    return 0;
}